package arithmetic.thread;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;

/**
 * @author jiangfeng 2019/7/15 23:57
 *CyclicBarrier 的demo类, 屏障:
 * 让一些线程阻塞直到另一些线程完成一系列操作后才被唤醒
 * countDownLatch主要有两个方法，当一个或多个线程调用await法时，调用线程会被阻塞。
 * 其它线程调用countDown万法会将计数器减1（调用countDown方法法的线程不会阻塞），当计数器的值变为零时，因调用await方法被阻塞的线程会被唤醒，继续执行。
 *
 * 一个疑问: 用junit 测试多线程会出问题??
 * 原因 ：junit主线程执行完毕就结束了，不管后台线程。  解决办法: 把junit的主线程阻塞一段时间即可.
 */
//@Slf4j
public class CyclicBarrierDemo {
    public static void main(String[] args) throws InterruptedException {
        int i = Runtime.getRuntime().availableProcessors();
        System.out.println(i);
        new CyclicBarrierDemo().test();
    }

    @Test
    public void test() throws InterruptedException {
        CyclicBarrier  cyclicBarrier = new CyclicBarrier(7,()->{
            System.out.println("集齐7课 开始召唤神龙!");
        }); // 集齐七颗龙珠召唤神龙

        for (int i = 0; i < 7; i++) {
            new Thread(() -> {
                try {
                    System.out.println(Thread.currentThread().getName()+" get");
                    cyclicBarrier.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }).start();
        }
        System.out.println(Thread.currentThread().getName()+" 完");

        Thread.sleep(3);
        //TimeUnit.SECONDS.sleep(5);
    }

    @Test
    public void testCyclicBarrier() throws InterruptedException {
        CyclicBarrier cyclicBarrier = new CyclicBarrier(7,()->{
            System.out.println("集齐7课 开始召唤神龙!");
        }); // 集齐七颗龙珠召唤神龙

        // ExecutorService executorService = Executors.newCachedThreadPool();
        // ExecutorService executorService = Executors.newSingleThreadExecutor();
        ExecutorService executorService = Executors.newFixedThreadPool(7);
        for (int i = 0; i < 7; i++) {
            executorService.submit(()->{ System.out.println(Thread.currentThread().getName()+" get");
                try {
                    cyclicBarrier.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            });
        }

        // 记得关闭线程池 要不然一直阻塞了.
        executorService.shutdown();

        Thread.sleep(15); // todo 为什么不阻塞住呢,下面这个确可以阻塞主,底层都一样啊??
        TimeUnit.SECONDS.sleep(8);


    }



}
